<?php

declare(strict_types=1);
/**
 * This file is part of Hyperf.
 *
 * @link     https://www.hyperf.io
 * @document https://hyperf.wiki
 * @contact  group@hyperf.io
 * @license  https://github.com/hyperf/hyperf/blob/master/LICENSE
 */

namespace App\Exception\Handler;

use App\Constants\Common\ApiStatusEnum;
use Hyperf\Context\Context;
use Hyperf\Contract\StdoutLoggerInterface;
use Hyperf\ExceptionHandler\ExceptionHandler;
use Hyperf\HttpMessage\Stream\SwooleStream;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Throwable;

/**
 * 应用异常处理类
 */
class AppExceptionHandler extends ExceptionHandler
{
        public function __construct(protected StdoutLoggerInterface $logger)
        {
        }

        public function handle(Throwable $throwable, ResponseInterface $response)
        {
                /*$this->logger->error(sprintf('%s[%s] in %s', $throwable->getMessage(), $throwable->getLine(), $throwable->getFile()));
                $this->logger->error($throwable->getTraceAsString());
                return $response->withHeader('Server', 'Hyperf')->withStatus(500)->withBody(new SwooleStream('Internal Server Error.'));*/
                $this->logger->error(sprintf('%s[%s] in %s', $throwable->getMessage(), $throwable->getLine(), $throwable->getFile()));
                $request = Context::get(ServerRequestInterface::class);
                if (strtolower($request->getMethod()) === 'options') {
                        return $this->configCrossDomainResponse($request, $response);
                }
                if ($request->getHeader('origin')) {
                        $response = $this->configCrossDomainResponse($request, $response);
                }
                $arrWith = businessError($throwable->getMessage(), ApiStatusEnum::INTERNAL_SERVER_ERROR->value);
                $jsonWith = json_encode($arrWith, JSON_UNESCAPED_UNICODE|JSON_UNESCAPED_SLASHES);
                return $response->withStatus(ApiStatusEnum::INTERNAL_SERVER_ERROR->value)->withBody(new SwooleStream($jsonWith));
        }

        /**
         * 配置跨域响应
         * @param ServerRequestInterface $request
         * @param ResponseInterface $response
         * @return ResponseInterface
         */
        private function configCrossDomainResponse(ServerRequestInterface $request, ResponseInterface $response): ResponseInterface
        {
                return $response
                        ->withHeader('Content-Type', $request->getHeader('content-type')[0] ?? 'application/json;charset=utf-8')
                        ->withHeader('Access-Control-Allow-Origin', $request->getHeader('origin')[0] ?? '*')
                        ->withHeader('Access-Control-Allow-Credentials', 'true')
                        ->withHeader('Access-Control-Allow-Headers', ACCESS_CONTROL_ALLOW_HEADERS)
                        ->withHeader('Access-Control-Allow-Methods', ACCESS_CONTROL_ALLOW_METHODS);
        }

        public function isValid(Throwable $throwable): bool
        {
                return true;
        }
}
